package ast;

import java.io.PrintStream;
import java.util.Map;
import java.util.Scanner;
import java.util.Stack;

public class AssignStmt extends Stmt {
    public final String ident;
    public final Expr expr;

    public AssignStmt(String i, Expr e, Location loc) {
        super(loc);
        ident = i;
        expr = e;
    }

    public void print(PrintStream ps, String indent) {
        ps.print(indent + ident + " = ");
        expr.print(ps);
        ps.print(";");
    }

    public void print(PrintStream ps) {
        print(ps, "");
    }

    // interpret: assign the value of the expression (right-hand side) to the variable (left-hand side)
    public void execute(Stack<Map<String, AbstractValue>> stateStack, Scanner scanner) throws Exception {
        // evaluate the expression
        AbstractValue exprValue = expr.evaluate(stateStack, scanner);

        /**
        // store the ident's abstract value
        AbstractValue identValue = null;
        Stack<Map<String, AbstractValue>> cloneStateStack = (Stack<Map<String, AbstractValue>>) stateStack.clone();

        while (!cloneStateStack.isEmpty()) {
            Map<String, AbstractValue> state = cloneStateStack.pop();
            if (state.containsKey(ident)) {
                identValue = state.get(ident);
                break;
            }
        }
        */

        // store the ident's abstract value on the top of the stack, IMPORTANT: this literally let later assignment read the innermost abstract value instead of outer. The top map is ditched when exiting the scope.
        stateStack.peek().put(ident, exprValue);
        return;
    }
}
